package spotview;

import com.sun.spot.io.j2me.radiogram.RadiogramConnection;
import com.sun.spot.util.CRC;
import com.sun.spot.util.Queue;
import com.sun.spot.util.Utils;
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;

/**
 *
 */
public class DeviceHandler {

    public static final String BROADCAST_ADDR = "radiogram://broadcast:110";
    public static final String ANYLISTEN_ADDR = "radiogram://:110";
    public static final int TRANSFER_QUEUE_SIZE = 1;
    public static final int TRANSFER_INTERVAL = 1000;
    Queue sendQueue;
    boolean cancelInvoked = false;
    Sender sender;
    Receiver receiver;
    Node node;

    public DeviceHandler(MainFrame frame) throws IOException {
        System.out.println("RelayNode started.");
        this.cancelInvoked = false;
        this.sendQueue = new Queue();
        this.sender = new Sender();
        this.receiver = new Receiver();
        this.node = new Node(this, frame);
    }

    public void work() {
        this.sender.start();
        this.receiver.start();
        this.node.work();
    }

    void stop() {
        cancelInvoked = true;
    }

    public void send(byte[] data) {
        sendQueue.put(data);
    }

    class Sender extends Thread {

        RadiogramConnection conn;
        Datagram buffer;

        Sender() throws IOException {

            conn = (RadiogramConnection) Connector.open(BROADCAST_ADDR);
            buffer = conn.newDatagram(conn.getMaximumLength());
        }

        public void run() {
            System.out.println("Start sending...");
            while (!cancelInvoked) {
                try {
                    byte[] data = (byte[]) sendQueue.get();
                    send(data);
                } catch (IOException ex) {
                    System.out.print("Exception[RelayNode.Sender]: ");
                    System.out.println(ex.getMessage());
                }
            }
        }

        void send(byte[] data) throws IOException {
            buffer.reset();
            short crc = CRC.crc(data, 0, data.length);
            buffer.writeShort(crc);
            buffer.write(data);
            conn.send(buffer);
        }
    }

    class Receiver extends Thread {

        RadiogramConnection conn;
        Datagram buffer;

        public Receiver() throws IOException {
            conn = (RadiogramConnection) Connector.open(ANYLISTEN_ADDR);
            buffer = conn.newDatagram(conn.getMaximumLength());
        }

        public void run() {
            System.out.println("Listening...");
            while (!cancelInvoked) {
                if (conn.packetsAvailable()) {
                    try {
                        byte[] msg = recv();
                        if (msg != null) {
                            node.onReceived(msg);
                        }
                    } catch (IOException e) {
                        System.out.print("Exception[RelayNode.Receiver]: ");
                        System.out.println(e.getMessage());
                    }

                } else {
                    Utils.sleep(100);
                }
            }
        }

        byte[] recv() throws IOException {
            buffer.reset();
            conn.receive(buffer);
            short sum = buffer.readShort();
            byte[] data = new byte[buffer.getLength() - 2];
            buffer.readFully(data);
            short actual = CRC.crc(data, 0, data.length);
            if (sum != actual) {
                System.out.println("Broken data.");
                return null;
            }
            return data;
        }
    }
}
